package com.sgcc.pda.bluetooth.bluetoothmanager;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

import com.sgcc.pda.bluetooth.api.IReceiveCallBack;
import com.sgcc.pda.bluetooth.blueinterface.BondCallBack;
import com.sgcc.pda.bluetooth.blueinterface.ConnectBlueCallBack;
import com.sgcc.pda.bluetooth.blueinterface.IOnFoundDeviceListener;
import com.sgcc.pda.bluetooth.blueinterface.IOnReConnectListener;
import com.sgcc.pda.bluetooth.bt.BtBase;
import com.sgcc.pda.bluetooth.bt.BtClient;
import com.sgcc.pda.bluetooth.config.Constant;
import com.sgcc.pda.bluetooth.entity.ReturnBean;
import com.sgcc.pda.bluetooth.utils.BlueDeviceInfoUtil;
import com.sgcc.pda.bluetooth.utils.ClsUtils;
import com.sgcc.pda.bluetooth.utils.StringUtil;
import com.sgcc.pda.bluetooth.utils.ToolGson;

import java.util.Timer;
import java.util.TimerTask;

import static com.sgcc.pda.bluetooth.config.Constant.BLUE_CLS;
import static com.sgcc.pda.bluetooth.config.Constant.CLS_CONN_OUT_TIME;
import static com.sgcc.pda.bluetooth.config.Constant.FLAG_RECONN;
import static com.sgcc.pda.bluetooth.utils.ClsUtils.hexString2Bytes;

/**
 * 描 述：经典蓝牙管理类
 * 可以自动连接上次连接的蓝牙对象、断开自动重连
 * 作 者：yangzhi
 * 时 间：2020/3/5 11:12
 * 版 本：1.0
 * 版 权： Copyright (c) remarkables-united.Co.Ltd. All rights reserved.
 */
public class ClassicBluetoothManager implements BtBase.Listener {

    private static final String TAG = "BlueManager";
    private static ClassicBluetoothManager mInstance;
    private Context context;
    private static BluetoothAdapter bluetoothAdapter;
    //搜索设备回调
    private static IOnFoundDeviceListener mOnFoundDeviceListener;
    //配对回调
    private static BondCallBack bondCallBack;
    //是否自动重连
    private boolean isAutoConnect = false;
    //超时时间
    private long outTime = CLS_CONN_OUT_TIME;
    //是否手动断开 手动断开不要再自动连接
    private boolean isActiveDisConnected;
    //自动重连次数
    private int mReConnCount;
    private int countFlag = 0;
    private IReceiveCallBack iReceiveCallBack;

    public static ClassicBluetoothManager getInstance(Context context) {
        synchronized (ClassicBluetoothManager.class) {
            if (null == mInstance) {
                mInstance = new ClassicBluetoothManager(context);
            }
        }
        return mInstance;
    }

    private ClassicBluetoothManager(Context context) {
        this.context = context;
    }


    /**
     * 经典蓝牙配置
     *
     * @param isAutoConnect 是否自动连接
     * @param reConnCount   最大重连次数
     */
    public void configBlue(boolean isAutoConnect, int reConnCount) {
        BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
        bluetoothAdapter = bluetoothManager.getAdapter();
        if (null == bluetoothAdapter) {
            Toast.makeText(context, "设备不支持蓝牙", Toast.LENGTH_SHORT).show();
            return;
        }
        this.isAutoConnect = isAutoConnect;
        this.mReConnCount = reConnCount;
        initBtBroadcast();
        //打开蓝牙
        bluetoothAdapter.enable();
    }


    /**
     * 是否手动断开的，手动断开不要自动连接
     *
     * @param isActiveDisConnected 是否手动断开
     */
    public void setActiveDisConnected(boolean isActiveDisConnected) {
        this.isActiveDisConnected = isActiveDisConnected;
    }


    /**
     * 设置连接的超时时间
     *
     * @param outTime 超时时间 ms
     */
    public void setOutTime(long outTime) {
        this.outTime = outTime;
    }


    /**
     * 判断蓝牙是否可用
     */
    public static boolean isBlueEnable() {
        return null != bluetoothAdapter && bluetoothAdapter.isEnabled();
    }

    /**
     * 扫描蓝牙设备
     *
     * @param onFoundDeviceListener 扫描监听
     *                              已连接的蓝牙放在列表第一项
     */
    public void scanDevice(IOnFoundDeviceListener onFoundDeviceListener) {
        mOnFoundDeviceListener = onFoundDeviceListener;
        if (null != bluetoothAdapter && !bluetoothAdapter.isEnabled()) {
            Intent enableIntent = new Intent("android.bluetooth.adapter.action.REQUEST_ENABLE");
            enableIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(enableIntent);
            return;
        }
        if (bluetoothAdapter.isDiscovering()) { //当前正在搜索设备...
            return;
        }
        //开始搜索
        bluetoothAdapter.startDiscovery();
    }


    /**
     * 蓝牙是否连接
     */
    public boolean isConnectBlue(BluetoothDevice bluetoothDevice) {
        return mClient.isConnected(bluetoothDevice);
    }


    /**
     * 自动扫描蓝牙设备
     */
    private static void scanDevice() {
        if (null != bluetoothAdapter) {
            return;
        }
        if (bluetoothAdapter.isDiscovering()) {
            //当前正在搜索设备...
            return;
        }
        /**
         * 先判断上次连接的蓝牙是否连接，已连接的话添加在第一个
         */
        BluetoothDevice lastDevice = BlueDeviceInfoUtil.getInstance().getClsDevice();
        if (null != lastDevice && mInstance.isConnectBlue(lastDevice)) {
            if (null != mOnFoundDeviceListener) {
                mOnFoundDeviceListener.clsFoundDevice(lastDevice);
            }
            Log.e(TAG, "添加上次连接的蓝牙：NAME:" + lastDevice.getName() + "MAC:" + lastDevice.getAddress());
        }
        //开始搜索
        bluetoothAdapter.startDiscovery();
    }


    /**
     * 取消扫描
     */
    public void cancelScan() {
        if (null != bluetoothAdapter && bluetoothAdapter.isDiscovering()) {
            bluetoothAdapter.cancelDiscovery();
        }
    }


    /**
     * 执行绑定
     *
     * @param bluetoothDevice 蓝牙设备
     * @return true 执行绑定 false 未执行绑定
     */
    public void boundDevice(BluetoothDevice bluetoothDevice, BondCallBack bondCallBack) {
        if (null == bluetoothDevice) {
            Log.e(TAG, "boundDevice-->bluetoothDevice == null");
            return;
        }
        if (null == bondCallBack) {
            return;
        }
        //配对之前把扫描关闭
        if (null != bluetoothAdapter && bluetoothAdapter.isDiscovering()) {
            bluetoothAdapter.cancelDiscovery();
        }
        //判断设备是否配对，没有配对在配，配对了就不需要配了
        if (bluetoothDevice.getBondState() == BluetoothDevice.BOND_NONE) {
            ClassicBluetoothManager.bondCallBack = bondCallBack;
            Log.e(TAG, "attemp to bond:" + bluetoothDevice.getName());
            try {
                ClsUtils.createBond(BluetoothDevice.class, bluetoothDevice);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 执行解绑
     *
     * @param bluetoothDevice 蓝牙设备
     * @return true 执行解绑  false未执行解绑
     */
    public void disBoundDevice(BluetoothDevice bluetoothDevice) {
        if (null == bluetoothDevice) {
            Log.e(TAG, "disBoundDevice-->bluetoothDevice == null");
            return;
        }
        //判断设备是否配对，没有配对就不用取消了
        if (bluetoothDevice.getBondState() != BluetoothDevice.BOND_NONE) {
            Log.d(TAG, "attemp to bond:" + bluetoothDevice.getName());
            try {
                ClsUtils.removeBond(BluetoothDevice.class, bluetoothDevice);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    //连接超时
    private Runnable connectOuttimeRunnable = new Runnable() {
        @Override
        public void run() {
            Log.e(TAG, "startConnectDevice-->连接超时");
            //断开管理连接
            ReturnBean returnBean = new ReturnBean();
            returnBean.setType(Constant.TYPE_RECEIVE);
            returnBean.setCode(Constant.RESULT_FAIL);
            returnBean.setData("连接超时");
            Log.e(TAG, " socketNotify 读取成功+连接超时");
            if (null != iReceiveCallBack) {
                iReceiveCallBack.receiveResult(returnBean);
            }
        }
    };


    /**
     * 输入mac地址进行自动配对
     * 前提是系统保存了该地址的对象
     *
     * @param address
     */
    public void connectMAC(String address, ConnectBlueCallBack connectBlueCallBack) {
        if (!isBlueEnable()) {
            return;
        }
        BluetoothDevice btDev = bluetoothAdapter.getRemoteDevice(address);
        connect(btDev, connectBlueCallBack);
    }

    /**
     * 判断系统是否保存了该mac地址的对象
     *
     * @param address
     */
    public boolean isConnectedDevice(String address) {
        BluetoothDevice btDev = bluetoothAdapter.getRemoteDevice(address);
        return btDev != null;
    }

    /**
     * 设置自动重连的监听
     */
    private IOnReConnectListener onReConnectListener;

    public void setAutoConnListener(IOnReConnectListener onReConnectListener) {
        this.onReConnectListener = onReConnectListener;
    }


    /**
     * 断开连接
     *
     * @return
     */
    public boolean cancelConnect() {
        if (null != mClient) mClient.close();
        return true;
    }


    /**
     * 连接
     *
     * @param device
     */
    private BtClient mClient = new BtClient(this);

    ConnectBlueCallBack connectBlueCallBack;

    public void connect(BluetoothDevice device, ConnectBlueCallBack connectBlueCallBack) {
        if (device == null) {
            Log.e(TAG, "bond device null");
            return;
        }
        if (!isBlueEnable()) {
            Log.e(TAG, "Bluetooth not enable!");
            return;
        }
        //连接之前把扫描关闭
        if (null != bluetoothAdapter && bluetoothAdapter.isDiscovering()) {
            bluetoothAdapter.cancelDiscovery();
        }

        if (mClient.isConnected(device)) {
            Log.e(TAG, "已经连接了");
            return;
        }
        if (null != connectBlueCallBack) {
            this.connectBlueCallBack = connectBlueCallBack;
            connectBlueCallBack.onStartConnect();
        }
        Log.e(TAG, "正在连接...");
        mClient.connect(device);
    }


    /**
     * 收发数据
     */

    public void sendData(final String data, final IReceiveCallBack callBack) {
        if (TextUtils.isEmpty(data)) {
            Log.e(TAG, "sendData:string-->要发送的数据为空");
            return;
        }
        //检查16进制数据是否合法
        if (data.length() % 2 != 0) {
            Log.e(TAG, "数据不合法");
            return;
        }
        Log.e(TAG, "sendData:-->准备写入：" + data);
        final byte[] bData = hexString2Bytes(data);
        this.iReceiveCallBack = callBack;
        if (mClient.isConnected(null)) {
            mClient.sendData(bData);
        } else {
            Log.e(TAG, "没有连接");
        }
//        mHandler.postDelayed(connectOuttimeRunnable, CLS_CONN_OUT_TIME);
    }


    /**
     * 自动重连
     * 每隔10s执行一次重连方法
     */
    private Timer timer;
    private TimerTask timerTask;

    private void autoConnTask(final BluetoothDevice bluetoothDevice) {
        countFlag = 0;
        if (null == timer) {
            timer = new Timer();
        }
        if (null == timerTask) {
            timerTask = new TimerTask() {
                @Override
                public void run() {
                    Message message = new Message();
                    message.what = FLAG_RECONN;
                    Bundle bundle = new Bundle();
                    if (null != bluetoothDevice) {
                        bundle.putParcelable(Constant.MESSAGE_CLS_KEY, bluetoothDevice);
                    }
                    message.setData(bundle);
                    mHandler.sendMessage(message);
                }
            };
        }
        try {
            timer.schedule(timerTask, 5000, Constant.CLS_CONN_OUT_TIME);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    private Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case FLAG_RECONN:
                    countFlag++;
                    //不是手动断开的情况并且少于设置的最大重连次数设置重连
                    Log.e(TAG, "mReConnCount:" + mReConnCount + "----countFlag:" + countFlag);
                    if (!isActiveDisConnected && countFlag <= mReConnCount) {
                        BluetoothDevice bluetoothDevice = msg.getData().getParcelable(Constant.MESSAGE_CLS_KEY);
                        if (null != bluetoothDevice) {
                            connect(bluetoothDevice, new ConnectBlueCallBack() {
                                @Override
                                public void onStartConnect() {
                                    Log.e(TAG, "开始自动重连");
                                    if (null != onReConnectListener) {
                                        onReConnectListener.onStartConn();
                                    }
                                }

                                @Override
                                public void onConnectSuccess(BluetoothDevice bluetoothDevice) {
                                    Log.e(TAG, "自动重连成功");
                                    clearTimer();
                                    if (null != bluetoothDevice) {
                                        Log.e(TAG, "连接成功，保存对象" + bluetoothDevice.getAddress());
                                        BlueDeviceInfoUtil.getInstance().setDeviceInfo(BLUE_CLS, ToolGson.getJsonStr(bluetoothDevice), CONNECTED);
                                    }
                                    if (null != onReConnectListener) {
                                        onReConnectListener.onConnSuccess();
                                    }
                                }

                                @Override
                                public void onConnectFail() {
                                    Log.e(TAG, "自动重连失败");
                                    if (null != onReConnectListener) {
                                        onReConnectListener.onConnFailure();
                                    }
                                }
                            });
                        }
                    } else {
                        try {
                            clearTimer();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                default:
                    break;
            }
        }
    };


    public void clearTimer() {
        if (null != timerTask) {
            timerTask.cancel();
            timerTask = null;
        }
        if (null != timer) {
            timer.cancel();
            timer = null;
        }
        if (null != mHandler) {
            mHandler.removeMessages(FLAG_RECONN);
        }
    }

    private String dataHex;

    @Override
    public void socketNotify(int state, Object obj) {
        String msg = null;
        switch (state) {
            case BtBase.Listener.CONNECTED:
                BluetoothDevice dev = (BluetoothDevice) obj;
                msg = String.format("与%s(%s)连接成功", dev.getName(), dev.getAddress());
                if (null != connectBlueCallBack) {
                    connectBlueCallBack.onConnectSuccess(dev);
                }
                Log.e("tag", msg);
                break;
            case BtBase.Listener.DISCONNECTED:
                msg = "连接断开";
                Log.e("tag", msg);
                if (null != connectBlueCallBack) {
                    connectBlueCallBack.onConnectFail();
                }
                break;
            case BtBase.Listener.MSG:
                mHandler.removeCallbacks(connectOuttimeRunnable);
                msg = String.format("\n%s", obj);
                Log.e(TAG, " socketNotify 获取数据" + msg);
                if (msg.length() < 40 && !msg.toUpperCase().endsWith("E9")) {
                    msg = StringUtil.replaceSpecialStr(msg);
                    dataHex = msg;
                    break;
                } else {
                    msg = StringUtil.replaceSpecialStr(msg);
                    msg = dataHex + msg;
                    String frameLen = msg.substring(24, 28);
                    frameLen = frameLen.substring(2, 4) + frameLen.substring(0, 2);
                    int leng = 20 + Integer.parseInt(frameLen, 16);
                    if (leng * 2 != msg.length()) {
                        dataHex = msg;
                        break;
                    } else {
                        dataHex = "";
                    }
                }
                Log.e("tag", msg);
                ReturnBean returnBean = new ReturnBean();
                returnBean.setType(Constant.TYPE_RECEIVE);
                returnBean.setCode(Constant.RESULT_SUCC);
                returnBean.setData(msg);
                Log.e(TAG, " socketNotify 读取成功");
                if (null != iReceiveCallBack) {
                    iReceiveCallBack.receiveResult(returnBean);
                }
                break;
        }
        Log.e(TAG, msg);
    }

    /**
     * 初始化蓝牙广播
     */
    private BtBroadcastReceiver btBroadcastReceiver;

    private void initBtBroadcast() {
        //注册广播接收
        btBroadcastReceiver = new BtBroadcastReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);//监听蓝牙状态的变化
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);//正在扫描
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//扫描完成
        intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//监听蓝牙绑定状态
        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);//搜索到设备
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);//蓝牙已连接
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); //远程设备的低级别（ACL）连接的断开
        context.registerReceiver(btBroadcastReceiver, intentFilter);
    }


    /**
     * 注册蓝牙广播接收器
     */
    public class BtBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {//正在搜索过程...
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                // 如果这个设备是不曾配对过的，添加到list列表
                if (null != mOnFoundDeviceListener) {
                    mOnFoundDeviceListener.clsFoundDevice(device);
                }
            } else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
                //经典蓝牙 开始扫描
                Log.e(TAG, "经典蓝牙开始扫描");
                if (null != mOnFoundDeviceListener) {
                    mOnFoundDeviceListener.bluetoothScanStart();
                }

            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                //经典蓝牙 扫描完成
                Log.e(TAG, "经典蓝牙扫描完成");
                if (null != mOnFoundDeviceListener) {
                    mOnFoundDeviceListener.bluetoothScanFinsh();
                }

            } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
                //经典蓝牙 断开已有的连接
                BluetoothDevice deviceDis = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                BluetoothDevice device = BlueDeviceInfoUtil.getInstance().getClsDevice();
                if (null != deviceDis && null != device && deviceDis.getAddress().equals(device.getAddress())) {
                    Log.e(TAG, "经典蓝牙断开");
                    //设置重连
                    if (!isActiveDisConnected && isAutoConnect && deviceDis.getAddress().equals(device.getAddress())) {
                        autoConnTask(device);
                    }
                }

            } else if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
                //经典蓝牙 建立连接
                Log.e(TAG, "经典蓝牙连接成功");
            } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
                //监听蓝牙连接状态
                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
                switch (state) {
                    case BluetoothAdapter.STATE_TURNING_ON://打开中
                        Log.e(TAG, "蓝牙打开中");
                        break;
                    case BluetoothAdapter.STATE_ON://已打开
                        Log.e(TAG, "蓝牙已打开");
                        //经典蓝牙 开始扫描
                        if (null != mOnFoundDeviceListener) {
                            scanDevice();
                        }
                        break;
                    case BluetoothAdapter.STATE_TURNING_OFF://关闭中
                        Log.e(TAG, "蓝牙关闭中");
                        break;
                    case BluetoothAdapter.STATE_OFF://已关闭
                        Log.e(TAG, "蓝牙已关闭");
                        break;
                    default:
                        break;
                }
            } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
                //绑定状态
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                switch (device.getBondState()) {
                    case BluetoothDevice.BOND_BONDING:// 正在配对
                        if (null != bondCallBack) {
                            bondCallBack.bonding(device);
                        }
                        break;
                    case BluetoothDevice.BOND_BONDED:// 配对结束
                        if (null != bondCallBack) {
                            bondCallBack.bonded(device);
                        }
                        break;
                    case BluetoothDevice.BOND_NONE:// 取消配对/未配对
                        if (null != bondCallBack) {
                            bondCallBack.cancelBond(device);
                        }
                        break;
                    default:
                        break;

                }

            }
        }
    }

    /**
     * 解除注册
     */
    public void unRegistReceiver() {
        if (null != btBroadcastReceiver) {
            context.unregisterReceiver(btBroadcastReceiver);
        }
    }


}
